﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using DevExpress.XtraGrid.Columns;
using DevExpress.XtraEditors.Registrator;
using DevExpress.XtraEditors.ViewInfo;
using DevExpress.XtraScheduler.UI;
using DevExpress.XtraEditors.Repository;
using System.ComponentModel.Design;
using DevExpress.XtraGrid;

namespace ProgNetDxComponents.Design.Creators
{
    [ToolboxItem(false)]
    public partial class GridColumnInfo : XtraUserControl
    {
        private const string EditNone = "<NULL>";
        public event EventHandler RepositoryCreated;

        private static Dictionary<string, EditorClassInfo> editors = new Dictionary<string, EditorClassInfo>();
        private static void AddInfo(EditorClassInfo info)
        {
            string name = info.Name;
            if (!editors.ContainsKey(name))
            {
                editors.Add(name, info);
            }
        }
        public static void GetAllRepositoryTypes(bool refresh = false)
        {
            if (refresh)
                editors.Clear();
            if (editors.Count == 0)
            {
                foreach (EditorClassInfo info in EditorRegistrationInfo.Default.Editors)
                {
                    AddInfo(info);
                }
                AddInfo(new EditorClassInfo("MonthEdit", typeof(MonthEdit), typeof(RepositoryItemMonth),
                typeof(ButtonEditViewInfo), new DevExpress.XtraEditors.Drawing.ButtonEditPainter(), true));
            }
        }

        private bool _LockEvents = false;
        private GridColumn _Column;
        private DataColumn _DataColumn = null;
        private IDesignerHost _Host;
        private Dictionary<string, RepositoryItem> repositories = new Dictionary<string, RepositoryItem>();

        private GridColumnInfo()
        {
            InitializeComponent();
        }
        public GridColumnInfo(GridColumn column, IDesignerHost host)
        {
            InitializeComponent();
            _Column = column;
            _Host = host;
            teName.Text = column.Name;
            teField.Text = column.FieldName;
            RefreshAvailableRepositories();
            GetAllRepositoryTypes();
            _DataColumn = GetColumn();
            foreach (string s in editors.Keys)
            {
                cbEditType.Properties.Items.Add(s);
            }
            if (_Column.ColumnEdit != null)
            {
                if (repositories.ContainsKey(_Column.ColumnEdit.Name))
                {
                    cbRepositories.SelectedItem = _Column.ColumnEdit.Name;
                }
                else
                    cbRepositories.SelectedItem = EditNone;
            }
            else
                cbRepositories.SelectedItem = EditNone;
            ceChanged.Checked = false;
            ceAssigned.Checked = _Column.ColumnEdit != null;
        }
        public static DataTable GetSourceTableForView(DevExpress.XtraGrid.Views.Base.BaseView view)
        {
            if (view.GridControl != null)
            {
                DataSet ds = null;
                string name = view.GridControl.DataMember;

                if (view.GridControl.DataSource is DataSet)
                {
                    ds = view.GridControl.DataSource as DataSet;
                }
                else
                {
                    if (view.GridControl.DataSource is DataTable)
                        return view.GridControl.DataSource as DataTable;
                    else if (view.GridControl.DataSource is BindingSource)
                    {
                        BindingSource s = view.GridControl.DataSource as BindingSource;
                        if (s.DataSource is DataTable)
                            return s.DataSource as DataTable;
                        else
                            if (s.DataSource is DataSet)
                            {
                                ds = s.DataSource as DataSet;
                                if (s.DataMember.IsNotNull())
                                    name = s.DataMember;
                            }
                    }
                }
                if (ds != null)
                {
                    if (name.IsNotNull() && ds.Tables.Contains(name) &&
                        (view == view.GridControl.MainView || view.SourceView == view.GridControl.MainView))
                    {
                        return ds.Tables[name];
                    }
                    else
                    {
                        GridLevelNode node = view.GridControl.LevelTree.Find(view);
                        if (node != null && node.RelationName.IsNotNull() && ds.Relations.Contains(node.RelationName))
                        {
                            return ds.Relations[node.RelationName].ChildTable;
                        }
                    }
                }
            }
            return null;
        }

        private DataColumn GetColumn()
        {
            if (_Column != null && _Column.View != null && _Column.FieldName.IsNotNull())
            {
                DataTable dt = GetSourceTableForView(_Column.View);
                if(dt!=null && dt.Columns.Contains(_Column.FieldName))
                {
                   return dt.Columns[_Column.FieldName];
                }
            }
            return null;
        }

        public void RefreshAvailableRepositories()
        {
            _LockEvents = true;
            object old = cbRepositories.EditValue;
            repositories.Clear();
            cbRepositories.Properties.Items.Clear();
            cbRepositories.Properties.Items.Add(EditNone);
            if (_Column != null && _Column.View != null && _Column.View.GridControl!=null)
            {
                foreach (RepositoryItem rep in _Column.View.GridControl.RepositoryItems)
                {
                    cbRepositories.Properties.Items.Add(rep.Name);
                    repositories.Add(rep.Name, rep);
                }
            }
            cbRepositories.EditValue = old;
            _LockEvents = false;
        }

        private void btnCreate_Click(object sender, EventArgs e)
        {
            try
            {
                string type = cbEditType.SelectedItem.AsString();
                if (editors.ContainsKey(type))
                {
                    string name = "rep" + _Column.FieldName.AsString().ToUpper();
                    int idx=1;
                    if (_Host.Container.Components[name] != null || repositories.ContainsKey(name))
                    {
                        while (_Host.Container.Components[name + idx] != null ||
                            repositories.ContainsKey(name + idx))
                        {
                            idx++;
                        }
                        name += idx;
                    }

                    RepositoryItem item = EditorRegistrationInfo.Default.CreateRepositoryItem(type);

                    if (item is RepositoryItemLookUpEditBase)
                    {
                        (item as RepositoryItemLookUpEditBase).ShowDropDown = DevExpress.XtraEditors.Controls.ShowDropDown.DoubleClick;
                    }

                    if (item is RepositoryItemTextEdit)
                    {
                        (item as RepositoryItemTextEdit).NullText = "";
                        if (_DataColumn != null)
                        {
                            if (_DataColumn.MaxLength > 0)
                            {
                                (item as RepositoryItemTextEdit).Mask.EditMask = ".{0," + _DataColumn.MaxLength + "}";
                                (item as RepositoryItemTextEdit).Mask.MaskType = DevExpress.XtraEditors.Mask.MaskType.RegEx;
                            }
                        }
                    }
                    if (item is RepositoryItemSpinEdit || item is RepositoryItemCalcEdit)
                    {
                        (item as RepositoryItemTextEdit).Mask.EditMask = "n2";
                        (item as RepositoryItemTextEdit).Mask.MaskType = DevExpress.XtraEditors.Mask.MaskType.Numeric;
                        (item as RepositoryItemTextEdit).Mask.UseMaskAsDisplayFormat = true;
                    }
                    if (item is RepositoryItemMemoExEdit)
                    {
                        (item as RepositoryItemMemoExEdit).ShowIcon = false;
                        (item as RepositoryItemMemoExEdit).ScrollBars = ScrollBars.Both;
                        (item as RepositoryItemMemoExEdit).WordWrap = false;
                        if (_DataColumn != null && _DataColumn.MaxLength > 0)
                        {
                            (item as RepositoryItemMemoExEdit).MaxLength = _DataColumn.MaxLength;
                        }
                    }

                    if (item is RepositoryItemButtonEdit)
                    {
                        (item as RepositoryItemButtonEdit).Buttons.Clear();
                        (item as RepositoryItemButtonEdit).CreateDefaultButton();
                        if ((item as RepositoryItemButtonEdit).Buttons.Count == 0)
                        {
                            (item as RepositoryItemButtonEdit).Buttons.Add(new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo));
                        }
                    }

                    _Column.View.GridControl.RepositoryItems.Add(item);
                    item.Name = name;
                    if (item.Site != null)
                        item.Site.Name = name;
                    item.SetPropertyValue("Name", name);

                    cbRepositories.Properties.Items.Add(item.Name);
                    repositories.Add(item.Name, item);
                    cbRepositories.SelectedItem = item.Name;

                    if (RepositoryCreated != null)
                        RepositoryCreated(this, EventArgs.Empty);
                }
            }
            catch (Exception ex)
            {
                ex.Log();
            }
        }

        private void cbRepositories_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (!_LockEvents)
            {
                string name = cbRepositories.SelectedItem.AsString();
                if (name != EditNone)
                {
                    propertyGridControl1.SelectedObject = repositories[name];
                    propertyGridControl1.RetrieveFields();
                }
                else
                {
                    propertyGridControl1.SelectedObject = null;
                }
                ceChanged.Checked = true;
            }
        }

        private void btnAssign_Click(object sender, EventArgs e)
        {
            AssignRepository();  
        }
        
        private void propertyGridControl1_CellValueChanged(object sender, DevExpress.XtraVerticalGrid.Events.CellValueChangedEventArgs e)
        {
            if (e.Row != null && e.Row.Properties.FieldName == "Name")
            {
                string name = e.Value.AsString();
                string oldName = cbRepositories.EditValue.AsString();

                repositories.Remove(oldName);
                repositories.Add(name, propertyGridControl1.SelectedObject as RepositoryItem);
                _LockEvents = true;
                cbRepositories.Properties.Items.Remove(oldName);
                cbRepositories.Properties.Items.Add(name);
                cbRepositories.EditValue = name;
                _LockEvents = false;
            }
        }

        public void AssignRepository()
        {
            string name = cbRepositories.SelectedItem.AsString();
            if (repositories.ContainsKey(name))
            {
                _Column.ColumnEdit = repositories[name];
                ceAssigned.Checked = true;
            }
            else
            {
                _Column.ColumnEdit = null;
                ceAssigned.Checked = false;
            }
            ceChanged.Checked = false;
        }
    }
}
